class Cons {
    constructor(car, cdr = undefined) {
        this.car = car;
        this.cdr = cdr;
    }

    static fromArray(arr, start = 0) {
        if (start >= arr.length - 1) {
            return new Cons(arr[start]);
        } else {
            return new Cons(arr[start], Cons.fromArray(arr, start + 1));
        }
    }

    toArray(arr = []) {
        arr.push(this.car);

        if (this.cdr) {
            this.cdr.toArray(arr);
        }

        return arr;
    }

    map(f, i = 0) {
        this.car = f(this.car, i, this);
        if (this.cdr) this.cdr.map(f, i+1);
    }

    get length() {
        if (this.cdr) {
            return 1 + this.cdr.length;
        } else {
            return this.car === undefined ? 0 : 1;
        }
    }

    *[Symbol.iterator]() {
        yield this.car;

        if (this.cdr) {
            yield* this.cdr[Symbol.iterator]();
        }
    }
}

export { Cons }